home *** CD-ROM | disk | FTP | other *** search
- char *version = "0.995 18-Apr-93";
- char *copyright = "Copyright (C) 1991, 1993, Trustees of Columbia University";
- /*
- textps - Convert plain text to Postscript.
-
- DESCRIPTION:
- Converts text files to PostScript Courier-11, 66 lines to the page, 80
- characters to the line. Handles pagination, tabs, line wrap, overstruck
- characters (via BS) and overstruck lines (via CR). Swallows and ignores
- (rather than printing) ANSI escape sequences. If the input file is
- already Postscript (i.e. if its first line starts with "%!"), it is simply
- copied to the output without alteration. No special effects like page
- headings, landscape, 2-up, etc.
-
- Unlike other "enscriptors", textps handles 8-bit character sets. The
- default file character set is CP437 on PCs, the NeXT character set on the
- NeXT, and ISO 8859-1 Latin Alphabet 1 elsewhere. CP850, DEC MCS, and
- Apple QuickDraw are also supported. Override the default character set
- with the -c command-line option. Shift-In/Shift-Out codes within the text
- are handled, so 8-bit characters can be encoded by ^N<char-128>^O in the
- 7-bit environment (e.g. e-mail) and still print correctly.
-
- USAGE:
- textps [ -h ] [ -v ] [ -c charset ] < input > output
-
- The input file character set is translated from the default character set
- or the one given on the command line to ISO Latin Alphabet 1, and the
- result is converted to Level-1 Postscript. The -h command line option
- prints a help message and exits immediately. The -v option includes a
- page showing the textps and PostScript version numbers. The -c option
- specifies the file's character set; charset may be latin1, cp437, cp850,
- decmcs, apple, or next.
-
- UNIX example: textps < file | lpr
- MS-DOS example: textps < file > prn
-
- Suggestion for use with DOS. Make a batch file called PSPRINT.BAT:
- @echo off
- textps < %1 > prn
-
- This assumes PRN is a Postscript printer. Works with both Postscript
- and non-Postscript files. Works with Novell CAPTURE. In VMS, make a
- DCL procedure similar to this batch file. In UNIX, use this program
- as a print filter (in /etc/printcap, or alias lpr='textps | lpr').
-
- ERRORS:
- Returns status code of 0 on success, 1 on failure.
- Only fails if it is invoked with invalid command line arguments,
- in which case an error and usage message is printed on stderr.
-
- BUGS:
- Not all the characters print on early model laserwriters or other very
- old PostScript printers: broken bar, copyright, trade mark, not sign,
- fractions, Y/y-acute and Icelandic Thorn/thorn and Eth/eth, etc. This
- is because these characters were not present in early PostScript releases.
-
- 8-bit characters are translated into an internal character set, which is
- ISO Latin Alphabet 1 with a few extensions, so any file characters that
- don't don't appear in this character set, such as PC line- and box-
- drawing characters, are approximated with characters like '+', '-', and
- '|'. Alphabetic or punctuation characters that have no equivalents in
- Latin-1 are shown as '?'.
-
- TO BUILD:
- Just compile it. If compiled under DOS with Microsoft C (and probably
- also under Xenix?), the default character set is CP437, on the NeXT
- it's the NeXT character set, otherwise it's Latin-1. On OS2, you might
- have to include -DOS2 on the C-compiler command line.
-
- To build with a particular default character set, include -DCHARSET=x
- on the cc command line, where x = 0 for Latin1, 1 for CP437, 2 for
- CP850, 3 for NeXT, 4 for DEC MCS, 5 for Apple QuickDraw.
-
- To disable ANSI-escape-sequence elimination, add -DNOESCSEQ.
-
- UPDATES:
- 0.95 5 Aug 91
- Add L procedure to output n blank lines, and don't bother to output
- blank lines after last text on page.
- 0.96 6 Aug 91
- Make sure a file that starts with Ctrl-L still outputs the PostScript
- prolog.
- 0.97 8 Aug 91
- Totally rewrite so we don't have to use backspacefont, which doesn't
- work if used too much. This also allows backspace overstriking to work
- across line wrap boundaries.
- 0.98 1 Oct 91
- Fix a few translation table entries.
- 0.99 7 Oct 91
- Fix the top and bottom margins so 66th line doesn't sometimes have
- descenders cut off.
- 0.995 18 Apr 93
- Fix output of already-PS files to not contain an unnecessary
- bufferful of blanks. Add #ifdef for default OS/2 character set.
- Remove compiler complaint about buf in printf.
- Reported by Darrel Hankerson at Auburn University.
-
- TO DO:
- Add support for 7-bit national ISO 646 character sets so we can
- print e-mail from Sweden, France, etc.
-
- Add support for Latin-2/CP852 East European character sets.
-
- Add support for different paper dimensions, e.g. European A4 Letter,
- US Legal, etc.
-
- Incorporate CP437 font from pc2ps program? (Box drawing chars, etc)
-
- Author: Frank da Cruz, Columbia University (fdc@columbia.edu), July 1991.
- Acks: For help with reencoding bugs: Bur Davis, Adobe.
-
- Copyright (C) 1985, 1993, Trustees of Columbia University in the City of New
- York. Permission is granted to any individual or institution to use this
- software as long as it is not sold for profit. This copyright notice must be
- retained. This software may not be included in commercial products without
- written permission of Columbia University.
-
- /* Defines and Includes... */
-
-
- #ifndef NOESCSEQ /* Swallow ANSI escape and control sequences */
- #define ESCSEQ /* unless -DNOESCSEQ given on cc command line. */
- #endif /* NOESCSEQ */
-
- #define WIDTH 80 /* Portrait printer line width, characters */
- #define LENGTH 66 /* Portrait printer page length, lines */
-
- /* Character set translations */
-
- #define UNK '?' /* What to translate an untranslatable character into */
- #define SP ' ' /* Space character */
- #define DEL 0177 /* DEL character */
-
- /* Character set symbols */
-
- #define LATIN1 0 /* ISO Latin Alphabet 1 */
- #define CP437 1 /* IBM code page 437 */
- #define CP850 2 /* IBM code page 850 */
- #define NEXT 3 /* NeXT character set */
- #define DECMCS 4 /* DEC multinational character set */
- #define APPLE 5 /* Apple QuickDraw character set */
-
- /* Default character set depends on where we're being compiled. */
-
- #ifdef __EMX__
- #ifndef OS2
- #define OS2
- #endif /* OS2 */
- #endif /* __EMX__ */
-
- #ifndef CHARSET /* If default not already defined */
- #ifdef MSDOS /* Symbol predefined by Microsoft C */
- #define CHARSET CP437 /* Default character set for PCs */
- #else
- #ifdef OS2
- #define CHARSET CP850 /* A little more modern for OS/2 */
- #else
- #ifdef NeXT /* Predefined by NeXT compiler */
- #define CHARSET NEXT
- #else
- #define CHARSET LATIN1 /* Default character set for others */
- #endif /* NeXT */
- #endif /* OS2 */
- #endif /* MSDOS */
- #endif /* CHARSET */
-
- #include <stdio.h> /* for EOF definition */
-
- /*
- Postscript Prolog, to be inserted at the beginning of the output file.
- The %% Comments are to make the file conformant with Adobe's "Postscript
- File Structuring Conventions", which allow page-oriented operations in
- Postscript previewers, page pickers, etc.
- */
- char *prolog[] = { /* Standard prolog */
- "%!PS-Adobe-1.0", /* Works with Postscript 1.0 */
- "%%Title: oofa",
- "%%DocumentFonts: Courier CourierLatin1",
- "%%Creator: textps",
- "%%Pages: (atend)",
- "%%EndComments",
- /*
- Postscript font reencoding. The standard encoding does not have the
- characters needed for Latin-1.
-
- Unfortunately, the font reencoding methods listed in the Postscript
- Cookbook simply do not work with the Apple Laserwriter (even though they
- did work with other Postscript devices). The method described in the
- Adobe PostScript Language Reference Manual (2nd Ed) to change from the
- StandardEncoding vector to the ISOLatin1Encoding vector works only with
- the LaserWriter-II, but not older LaserWriters.
-
- This method, suggested by Bur Davis at Adobe, works around the fact that
- Courier was a "stroke font" in pre-version-47.0 Postscript, in which many of
- the accented characters are composed from other characters (e.g. i-grave =
- dotless i + grave). It is probably not the most efficient possible solution
- (an iterative method might be better), but it works.
- */
- "/CourierLatin1 /Courier findfont dup dup maxlength dict begin",
- "{",
- " 1 index /FID ne { def } { pop pop } ifelse",
- "} forall",
- "/Encoding exch 1 index get 256 array copy def",
- /*
- The following characters are added at the C1 positions 128-153, for printing
- non-Latin1 character sets such as IBM code pages, DEC MCS, NeXT, etc. Note
- that we cannot use characters from the Symbol font. Characters from
- different fonts cannot be mixed. Anyway, the Symbol font is not fixed-width.
- */
- "Encoding 128 /quotesingle put",
- "Encoding 129 /quotedblleft put",
- "Encoding 131 /fi put",
- "Encoding 132 /endash put",
- "Encoding 133 /dagger put",
- "Encoding 134 /periodcentered put",
- "Encoding 135 /bullet put",
- "Encoding 136 /quotesinglbase put",
- "Encoding 137 /quotedblbase put",
- "Encoding 138 /quotedblright put",
- "Encoding 139 /ellipsis put",
- "Encoding 140 /perthousand put",
- "Encoding 141 /dotaccent put",
- "Encoding 142 /hungarumlaut put",
- "Encoding 143 /ogonek put",
- "Encoding 144 /caron put",
- "Encoding 145 /fl put",
- "Encoding 146 /emdash put",
- "Encoding 147 /Lslash put",
- "Encoding 148 /OE put",
- "Encoding 149 /lslash put",
- "Encoding 150 /oe put",
- "Encoding 151 /florin put",
- "Encoding 152 /fraction put",
- "Encoding 153 /daggerdbl put",
- /*
- The following six characters are required for pre-47.0 PostScript versions,
- which compose accented Courier characters by putting together the base
- character and the accent.
- */
- "Encoding 154 /dotlessi put",
- "Encoding 155 /grave put",
- "Encoding 156 /circumflex put",
- "Encoding 157 /tilde put",
- "Encoding 158 /breve put",
- "Encoding 159 /ring put",
- /*
- The remainder follow the normal ISO 8859-1 encoding.
- */
- "Encoding 160 /space put",
- "Encoding 161 /exclamdown put",
- "Encoding 162 /cent put",
- "Encoding 163 /sterling put",
- "Encoding 164 /currency put",
- "Encoding 165 /yen put",
- "Encoding 166 /brokenbar put",
- "Encoding 167 /section put",
- "Encoding 168 /dieresis put",
- "Encoding 169 /copyright put",
- "Encoding 170 /ordfeminine put",
- "Encoding 171 /guillemotleft put",
- "Encoding 172 /logicalnot put",
- "Encoding 173 /hyphen put",
- "Encoding 174 /registered put",
- "Encoding 175 /macron put",
- "Encoding 176 /degree put",
- "Encoding 177 /plusminus put",
- "Encoding 178 /twosuperior put",
- "Encoding 179 /threesuperior put",
- "Encoding 180 /acute put",
- "Encoding 181 /mu put",
- "Encoding 182 /paragraph put",
- "Encoding 183 /bullet put",
- "Encoding 184 /cedilla put",
- "Encoding 185 /onesuperior put",
- "Encoding 186 /ordmasculine put",
- "Encoding 187 /guillemotright put",
- "Encoding 188 /onequarter put",
- "Encoding 189 /onehalf put",
- "Encoding 190 /threequarters put",
- "Encoding 191 /questiondown put",
- "Encoding 192 /Agrave put",
- "Encoding 193 /Aacute put",
- "Encoding 194 /Acircumflex put",
- "Encoding 195 /Atilde put",
- "Encoding 196 /Adieresis put",
- "Encoding 197 /Aring put",
- "Encoding 198 /AE put",
- "Encoding 199 /Ccedilla put",
- "Encoding 200 /Egrave put",
- "Encoding 201 /Eacute put",
- "Encoding 202 /Ecircumflex put",
- "Encoding 203 /Edieresis put",
- "Encoding 204 /Igrave put",
- "Encoding 205 /Iacute put",
- "Encoding 206 /Icircumflex put",
- "Encoding 207 /Idieresis put",
- "Encoding 208 /Eth put",
- "Encoding 209 /Ntilde put",
- "Encoding 210 /Ograve put",
- "Encoding 211 /Oacute put",
- "Encoding 212 /Ocircumflex put",
- "Encoding 213 /Otilde put",
- "Encoding 214 /Odieresis put",
- "Encoding 215 /multiply put",
- "Encoding 216 /Oslash put",
- "Encoding 217 /Ugrave put",
- "Encoding 218 /Uacute put",
- "Encoding 219 /Ucircumflex put",
- "Encoding 220 /Udieresis put",
- "Encoding 221 /Yacute put",
- "Encoding 222 /Thorn put",
- "Encoding 223 /germandbls put",
- "Encoding 224 /agrave put",
- "Encoding 225 /aacute put",
- "Encoding 226 /acircumflex put",
- "Encoding 227 /atilde put",
- "Encoding 228 /adieresis put",
- "Encoding 229 /aring put",
- "Encoding 230 /ae put",
- "Encoding 231 /ccedilla put",
- "Encoding 232 /egrave put",
- "Encoding 233 /eacute put",
- "Encoding 234 /ecircumflex put",
- "Encoding 235 /edieresis put",
- "Encoding 236 /igrave put",
- "Encoding 237 /iacute put",
- "Encoding 238 /icircumflex put",
- "Encoding 239 /idieresis put",
- "Encoding 240 /eth put",
- "Encoding 241 /ntilde put",
- "Encoding 242 /ograve put",
- "Encoding 243 /oacute put",
- "Encoding 244 /ocircumflex put",
- "Encoding 245 /otilde put",
- "Encoding 246 /odieresis put",
- "Encoding 247 /divide put",
- "Encoding 248 /oslash put",
- "Encoding 249 /ugrave put",
- "Encoding 250 /uacute put",
- "Encoding 251 /ucircumflex put",
- "Encoding 252 /udieresis put",
- "Encoding 253 /yacute put",
- "Encoding 254 /thorn put",
- "Encoding 255 /ydieresis put",
- "currentdict end definefont",
- /*
- Set the font and define functions for adding lines and printing pages.
- */
- "/CourierLatin1 findfont 11 scalefont setfont",
- "/StartPage{/sv save def 48 765 moveto}def",
- "/ld -11.4 def", /* Line spacing */
- "/yline 765 def", /* Position of top line */
- "/U{show", /* Show line, don't advance */
- " 48 yline moveto}def",
- "/S{show", /* Show line, move to next line */
- " /yline yline ld add def",
- " 48 yline moveto}def",
- "/L{ld mul yline add /yline exch def", /* Move down n lines */
- " 48 yline moveto}def",
- "/EndPage{showpage sv restore}def",
- "%%EndProlog", /* End of prolog. */
- "%%Page: 1 1", /* Number the first page. */
- "StartPage", /* And start it. */
- "" /* Empty string = end of array. */
- };
-
- /*
- Translation tables from local character sets into CourierLatin1.
- */
-
- /*
- IBM Code Page 437. Line- and box-drawing characters are simulated with
- dashes, bars, and plus signs. Black and gray blobs (fill characters)
- are replaced by X's. Peseta is shown as P. Greek letters that don't
- exist in CourierLatin1 are shown as ?. Untranslatable math symbols are
- shown as ?.
- */
- unsigned char
- y43l1[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238, 236, 196, 197,
- 201, 230, 198, 244, 246, 242, 251, 249, 255, 214, 220, 162, 163, 165, 'P', 151,
- 225, 237, 243, 250, 241, 209, 170, 186, 191, '+', 172, 189, 188, 161, 171, 187,
- 'X', 'X', 'X', '|', '+', '+', '+', '+', '+', '+', '|', '+', '+', '+', '+', '+',
- '+', '+', '+', '+', '-', '+', '+', '+', '+', '+', '+', '+', '+', '-', '+', '+',
- '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', 'X', 'X', 'X', 'X', 'X',
- UNK, 223, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK,
- UNK, 177, UNK, UNK, UNK, UNK, UNK, UNK, 176, 134, 135, UNK, 'n', 178, 'X', 160
- };
-
- /*
- IBM Code Page 850. Line- and box-drawing characters are simulated with
- dashes, bars, and plus signs. Black blobs are replaced by X's.
- */
- unsigned char
- y85l1[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238, 236, 196, 197,
- 201, 230, 198, 244, 246, 242, 251, 249, 255, 214, 220, 248, 163, 216, 215, 151,
- 225, 237, 243, 250, 241, 209, 170, 186, 191, 174, 172, 189, 188, 161, 171, 187,
- 'X', 'X', 'X', '|', '+', 193, 194, 192, 169, '+', '|', '+', '+', 162, 165, '+',
- '+', '+', '+', '+', '-', '+', 227, 195, '+', '+', '+', '+', '+', '-', '+', 164,
- 240, 208, 202, 203, 200, 154, 205, 206, 207, '+', '+', 'X', 'X', 166, 204, 'X',
- 211, 223, 212, 210, 245, 213, 181, 254, 222, 218, 219, 217, 253, 221, 175, 180,
- 173, 177, '=', 190, 182, 167, 247, 184, 176, 168, 134, 185, 179, 178, 'X', 160
- };
-
- /*
- NeXT character set. Here we have a full translation.
- */
- unsigned char
- ynel1[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 160, 192, 193, 194, 195, 196, 197, 199, 200, 201, 202, 203, 204, 205, 206, 207,
- 208, 209, 210, 211, 212, 213, 214, 217, 218, 219, 220, 221, 222, 181, 215, 247,
- 169, 161, 162, 163, 152, 165, 151, 167, 164, 128, 129, 171, '<', '>', 131, 145,
- 174, 132, 133, 153, 134, 166, 182, 135, 136, 137, 138, 187, 139, 140, 172, 191,
- 185, 96, 180, 94, 126, 175, 158, 141, 168, 178, 176, 184, 179, 142, 143, 144,
- 146, 177, 188, 189, 190, 224, 225, 226, 227, 228, 229, 231, 232, 233, 234, 235,
- 236, 198, 237, 170, 238, 239, 240, 241, 147, 216, 148, 186, 242, 243, 244, 245,
- 246, 230, 249, 250, 251, 154, 252, 253, 149, 248, 150, 223, 254, 255, ' ', ' '
- };
-
- /*
- DEC Multinational Character Set (MCS).
- */
- unsigned char
- ydml1[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
- 160, 161, 162, 163, ' ', 165, ' ', 167, 164, 169, 170, 171, ' ', ' ', ' ', ' ',
- 176, 177, 178, 179, ' ', 181, 182, 134, ' ', 185, 186, 187, 188, 189, ' ', 191,
- 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
- ' ', 209, 210, 211, 212, 213, 214, 148, 216, 217, 218, 219, 220, 221, ' ', 223,
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
- ' ', 241, 242, 243, 244, 245, 246, 150, 248, 249, 250, 251, 252, 255, ' ', ' ',
- };
-
- /*
- Apple QuickDraw character set.
- */
- unsigned char
- yaql1[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 196, 197, 199, 201, 209, 214, 220, 225, 224, 226, 228, 227, 229, 231, 233, 232,
- 234, 235, 237, 236, 238, 239, 241, 243, 242, 244, 246, 245, 250, 249, 251, 252,
- 133, 176, 162, 163, 167, 135, 182, 223, 174, 169, UNK, 180, 168, UNK, 198, 216,
- UNK, 177, UNK, UNK, 165, 181, UNK, UNK, UNK, UNK, UNK, 170, 186, UNK, 230, 248,
- 191, 161, 172, UNK, 151, UNK, UNK, 171, 187, 139, ' ', 193, 195, 213, 148, 150,
- 132, 146, 129, 138, 47, 47, 247, UNK, 255, UNK, 152, 164, '<', '>', 131, 145,
- 153, 134, 136, 137, 140, 194, 202, 192, 203, 200, 205, 206, 207, 204, 211, 212,
- UNK, 210, 218, 219, 217, 154, 156, 157, 175, 158, 141, 176, 184, 142, 143, 144
- };
-
- /*
- Data structures and functions for parsing and displaying character set name.
- */
- struct keytab { /* Keyword table template */
- char *kwd; /* Pointer to keyword string */
- int kwval; /* Associated value */
- };
-
- struct keytab csets[] = { /* Character sets, alphabetical */
- "apple", APPLE, /* Apple QuickDraw */
- "cp437", CP437, /* IBM Code Page 437 */
- "cp850", CP850, /* IBM Code Page 850 */
- "decmcs", DECMCS, /* DEC Multinational Character Set */
- "latin1", LATIN1, /* ISO 8859-1 Latin Alphabet 1 */
- "next", NEXT /* NeXT character set */
- };
- int ncsets = (sizeof(csets) / sizeof(struct keytab));
-
- int
- lower(s) char *s; { /* Lowercase the string */
- int n = 0; /* return its length */
- while (*s) {
- if (*s >= 'A' && *s <= 'Z')
- *s += ('A' - 'a');
- s++, n++;
- }
- return(n);
- }
-
- /* Look up keyword, return value */
-
- int
- lookup(table,cmd,n,x) char *cmd; struct keytab table[]; int n, *x; {
-
- int i, v, cmdlen;
-
- /* Lowercase & get length of target, if it's null return code -3. */
-
- if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
-
- /* Not null, look it up */
-
- for (i = 0; i < n-1; i++) {
- if (!strcmp(table[i].kwd,cmd) ||
- ((v = !strncmp(table[i].kwd,cmd,cmdlen)) &&
- strncmp(table[i+1].kwd,cmd,cmdlen))) {
- *x = i;
- return(table[i].kwval);
- }
- if (v) return(-2);
- }
-
- /* Last (or only) element */
-
- if (!strncmp(table[n-1].kwd,cmd,cmdlen)) {
- *x = n-1;
- return(table[n-1].kwval);
- } else return(-1);
- }
-
- /* Look up value, return keyword */
-
- char *
- getname(x,table,n) int x, n; struct keytab table[]; {
- int i;
- for (i = 0; i < n; i++)
- if (table[i].kwval == x)
- return(table[i].kwd);
- return("");
- }
-
- /* Global data */
-
- int charset = CHARSET, /* Character set */
- hpos = 0, /* Character number in line buffer */
- maxhpos = 0, /* Longest line in buffer */
- page = 0, /* Page number */
- line = 0, /* Line number */
- blank = 0, /* Blank line count */
- pagefull = 0, /* Flag for page overflow */
- psflag = 0, /* Flag for file already postscript */
- proflg = 0, /* Prolog done */
- shift = 0; /* Shift state */
-
- /* Data structures */
-
- /*
- buf is the line buffer. columns (indexed by hpos) are the characters
- in the line, rows are overstruck lines. At display time (see addline),
- buf is treated as a 3-dimensional array, with the extra dimension being
- for wraparound. The total size of the buffer is 80 chars per line times
- 66 lines per page times 10 levels of overstriking = 52,800. This allows
- files that contain absolutely no linefeeds to still print correctly.
- */
- #define BUFNUM 10 /* Number of overstrike buffers */
- #define BUFWID 5280 /* Max characters per line */
-
- unsigned char buf[BUFNUM][BUFWID]; /* Line buffers */
- unsigned char outbuf[400]; /* Output buffer */
- int linesize[BUFNUM]; /* Size of each line in buffer */
- int bufs[LENGTH]; /* # overstrike buffers per line */
-
- /* Line and page display routines */
-
- /* Forward declarations */
-
- void addline(); /* Add line to page */
- void addchar(); /* Add character to line */
- void newpage(); /* New page */
- void usage(); /* Usage message */
-
- void
- clearbuf() { /* Clear line buffer */
- int i;
- unsigned char *p, *q;
- /*
- Note: if a loop is used instead of memset, this program runs
- very slooooooowly.
- */
- memset(buf,SP,BUFNUM * BUFWID); /* Clear buffers and counts */
- for (i = 0; i < BUFNUM; linesize[i++] = -1) ;
- for (i = 0; i < LENGTH; bufs[i++] = 0) ;
- hpos = 0; /* Reset line buffer pointer */
- maxhpos = 0; /* And maximum line length */
- }
-
- void
- doprolog() { /* Output the PostScript prolog */
- int i;
- for (i = 0; *prolog[i]; i++) {
- printf("%s\n",prolog[i]);
- proflg++;
- }
- }
-
- void
- addchar(c) unsigned char c; { /* Add character to line buffer */
- int i, m;
-
- if (c < SP || c == DEL) c = SP; /* ASCII controls become spaces. */
-
- if (c > 127) { /* 8-bit values are translated */
- switch (charset) { /* according to character set. */
- case LATIN1:
- if (c > 127 && c < 161) /* C1 characters are controls */
- c = SP; /* in Latin-1. */
- break;
- case CP437: c = y43l1[c]; break;
- case CP850: c = y85l1[c]; break;
- case NEXT: c = ynel1[c]; break;
- case DECMCS: c = ydml1[c]; break;
- case APPLE: c = yaql1[c]; break;
- }
- }
- for (i = 0; i < BUFNUM; i++) { /* Find first */
- if (hpos > linesize[i]) { /* available overstrike buffer */
- buf[i][hpos] = c; /* Deposit character */
- linesize[i] = hpos; /* Remember size of this buffer. */
- m = hpos / WIDTH; /* Line-wrap segment number. */
- if (i > bufs[m]) bufs[m] = i; /* Highest overstrike buffer used */
- break; /* for this line-wrap segment. */
- }
- }
- if (hpos > maxhpos) maxhpos = hpos; /* Remember maximum line position. */
- if (++hpos >= BUFWID) /* Increment line position. */
- addline(); /* If buffer full, dump it. */
- }
-
- void
- addline() { /* Add a line to the current page */
- int i, j, k, m, n, y, wraps;
- unsigned char *p, *q, c;
-
- if (line == 0 && page == 1) { /* First line of file? */
- if (!strncmp(buf,"%!",2)) { /* Already Postscript? */
- unsigned char * t; /* Yes, just copy the file */
- psflag++; /* Set this flag to remember. */
- t = buf[0] + hpos; /* Trim trailing blanks */
- *t = '\0';
- printf("%s\n",buf[0]); /* Send this line to stdout */
- return;
- } else if (!proflg) { /* Not Postscript, print prolog. */
- doprolog();
- }
- }
- if (linesize[0] < 0) { /* If line is empty, */
- blank++; /* just count it. */
- return;
- }
- if (blank > 0) { /* Any previous blank lines? */
- if (blank == 1) /* One */
- printf("()S\n");
- else /* Many */
- printf("%d L\n",blank);
- }
- line += blank; /* Count the blank lines */
- blank = 0; /* Reset blank line counter */
-
- wraps = maxhpos / WIDTH; /* Number of times line will wrap */
- if (wraps > LENGTH) wraps = LENGTH; /* (within reason) */
-
- for (k = 0; k <= wraps; k++) { /* For each wrapped line */
- m = k * WIDTH; /* Starting position in buffer */
- for (i = 0; i <= bufs[k]; i++) { /* For each overstrike buffer */
- y = linesize[i] + 1; /* Actual character count */
- if (y <= m) /* Nothing there, next buffer. */
- continue;
- /* Ending position of this wrap region in buffer. */
- n = (y < m + WIDTH) ? y : m + WIDTH;
- q = outbuf;
- *q++ = '('; /* Start text arg */
- for (j = m, p = buf[i]+m; j < n; j++) { /* For each character */
- c = *p++;
- if (c == '(' || c == ')' || c =='\\') /* Quote specials */
- *q++ = '\\'; /* with backslash. */
- if ((int) c < 128) /* Insert 7-bit character literally */
- *q++ = c;
- else { /* Insert 8-bit character */
- *q++ = '\\'; /* as octal backslash escape */
- *q++ = (c >> 6) + '0'; /* (this avoids call to sprintf) */
- *q++ = ((c >> 3) & 07) + '0';
- *q++ = (c & 07) + '0';
- }
- }
- *q = '\0';
- printf("%s%s",outbuf, (i == bufs[k]) ? ")S\n" : ")U\n");
- }
- }
- clearbuf(); /* Clear line buffer */
- line += wraps + 1; /* Increment line number */
- if (line > (LENGTH - 1)) { /* If page is full */
- newpage(); /* print it and start new one */
- pagefull = 1;
- }
- }
-
- void
- newpage() { /* Print current page, start new one */
- if (pagefull) { /* If we just overflowed onto a */
- pagefull = 0; /* new page, but then got a formfeed */
- return; /* immediately after... */
- }
- if (!proflg) /* Do prolog if not done already */
- doprolog(); /* (in case file starts with ^L) */
- if (hpos) /* Add any partial line */
- addline();
- line = hpos = 0; /* Reset line, advance page */
- page++;
- printf("EndPage\n%%%%Page: %d %d\nStartPage\n",page,page);
- blank = 0;
- }
-
- void /* Show program & PostScript version numbers */
- showver() {
- printf("%%!\n/Courier findfont 11 scalefont setfont\n");
- printf("/EndPage{version (PostScript version )\n");
- printf("48 720 moveto show show showpage sv restore}def\n");
- printf("/sv save def 48 740 moveto\n");
- printf("(textps version %s) show\n",version);
- printf("/sv save def 48 700 moveto\n");
- printf("(textps %s) show\n",copyright);
- printf("EndPage\n");
- }
-
- /* Main program */
-
- void
- main(argc, argv) int argc; char *argv[]; {
-
- int i, j, /* Worker ints */
- escape; /* Flag when Esc seen. */
- unsigned char c; /* Input character */
-
- while (--argc > 0) { /* argv/argc "User interface"... */
- argv++;
- if (**argv == '-') { /* Look for '-' */
- c = *(*argv+1); /* Get option letter */
- switch (c) {
- case 'h': case 'H': case '?': /* Help */
- usage(-1);
- case 'c': case 'C': /* Character set */
- argv++, argc--;
- if (argc < 1) usage(4);
- i = lookup(csets,*argv,ncsets,&j);
- if (i < 0) usage(-i);
- charset = i;
- break;
- case 'v': case 'V': /* Show version numbers */
- showver();
- break;
- default:
- usage(5);
- }
- } else { /* Options must begin with '-' */
- usage(0);
- }
- }
- hpos = line = psflag = 0; /* Initialize these... */
- escape = blank = 0;
- page = 1;
-
- clearbuf(); /* Clear line buffer. */
-
- while ((i = getchar()) != EOF) { /* Read a file character */
- c = i; /* Convert to unsigned char */
- if (psflag) { /* File already postscript? */
- putchar(c); /* Just copy the bytes. */
- continue;
- }
- #ifdef ESCSEQ
- if (escape) { /* Swallow ANSI escape sequences */
- switch (escape) {
- case 1: /* ESC */
- if (c < 040 || c > 057) /* Not intermediate character */
- escape = 0;
- continue;
- case 2: /* CSI */
- if (c < 040 || c > 077) /* Not parameter or intermediate */
- escape = 0;
- continue;
- default: /* Bad escape value, */
- escape = 0; /* shouldn't happen. */
- break;
- }
- }
- #endif /* ESCSEQ */
-
- if (shift && c > 31 && c < 127)
- c |= 0200; /* Handle shift state. */
-
- if (pagefull && c != 014) /* Spurious blank page suppression */
- pagefull = 0;
-
- switch (c) { /* Handle the input character */
-
- case 010: /* Backspace */
- hpos--;
- if (hpos < 0) hpos = 0;
- continue;
-
- case 011: /* Tab */
- hpos = (hpos | 7) + 1;
- continue;
-
- case 012: /* Linefeed */
- addline(); /* Add the line to the page */
- continue;
-
- case 014: /* Formfeed */
- newpage(); /* Print current page */
- continue;
-
- case 015: /* Carriage return */
- hpos = 0; /* Back to left margin */
- continue;
-
- case 016: /* Shift-Out */
- shift = 1; /* Set shift state */
- continue;
-
- case 017: /* Shift-In */
- shift = 0; /* Reset shift state */
- continue;
-
- #ifdef ESCSEQ /* Swallow ANSI escape sequences */
- /*
- 1 = ANSI escape sequence
- 2 = ANSI control sequence
- */
- case 033: /* ESC or 7-bit CSI */
- escape = ((c = getchar()) == 0133) ? 2 : 1;
- if (c != 033 && c != 0133 && c != 233) /* Not ANSI after all */
- ungetc(c,stdin); /* put it back, avoid loops */
- continue;
-
- case 0233: /* 8-bit CSI */
- if (charset == LATIN1) {
- escape = 2; /* 0233 is graphic char on PC, etc */
- continue;
- } /* Otherwise fall thru & print it */
- #endif /* ESCSEQ */
-
- default:
- addchar(c);
- }
- }
- if (!psflag) { /* Done. If not postscript already, */
- if (hpos) /* if last line was not empty, */
- addline(); /* add it to the page. */
- if (page != 1 || line != 0) { /* Add trailer. */
- printf("EndPage\n%%%%Trailer\n%%%%Pages: %d\n",page);
- }
- }
- exit(0); /* Done, return success code. */
- }
-
- void
- usage(x) int x; { /* Give usage message and quit. */
- int i;
- switch (x) {
- case 0:
- fprintf(stderr,"textps: only options, not filenames, allowed;");
- fprintf(stderr," use standard input.\n");
- break;
- case 1:
- fprintf(stderr,"textps: invalid character set name\n");
- break;
- case 2:
- fprintf(stderr,"textps: ambiguous option\n");
- break;
- case 3:
- fprintf(stderr,"textps: option required after -\n");
- break;
- case 4:
- fprintf(stderr,"textps: option requires an argument\n");
- break;
- case 5:
- fprintf(stderr,"textps: invalid option\n");
- break;
- default:
- break;
- }
- fprintf(stderr,
- "textps converts standard input to PostScript on standard output.\n");
- fprintf(stderr,
- "if standard input is already in PostScript format, it is simply copied.\n");
- fprintf(stderr,
- "usage: textps [ -h ] [ -v ] [ -c charset ] < infile > outfile\n");
- fprintf(stderr," -h displays this usage message.\n");
- fprintf(stderr,
- " -v produces a page showing textps and PostScript version numbers.\n");
- fprintf(stderr,
- " -c specifies the file's character set, one of the following:\n");
- for (i = 0; i < ncsets; i++)
- fprintf(stderr," %s\n",csets[i].kwd);
- fprintf(stderr," the default character set is %s.\n",
- getname(charset,csets,ncsets));
- fprintf(stderr,"examples:\n");
- fprintf(stderr," textps < infile > outfile\n");
- fprintf(stderr," textps -v < infile > outfile\n");
- fprintf(stderr," textps -c cp850 < infile > outfile\n");
- fprintf(stderr," textps -v -c next < infile > outfile\n");
- fprintf(stderr," textps < infile | lpr (UNIX)\n");
- fprintf(stderr," textps < infile > prn (DOS)\n");
- fprintf(stderr,"textps version: %s.\n",version);
- fprintf(stderr,"%s\n",copyright);
- exit(1);
- }
-